package com.canbot.u05.activity

import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.*
import android.support.annotation.DrawableRes
import android.support.annotation.LayoutRes
import android.support.annotation.StringRes
import android.support.v4.app.Fragment
import android.view.*
import android.widget.ImageView
import android.widget.Toast
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.canbot.u05.R
import com.canbot.u05.utils.Logger
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.Serializable
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

fun Activity.showToast(string: String) {
    this.runOnUiThread {
        val toast = Toast.makeText(this, string, Toast.LENGTH_SHORT)
        toast.setGravity(Gravity.BOTTOM, 0, 0)
        toast.show()
    }
}

fun Activity.showToast(@StringRes resId: Int) {
    showToast(getString(resId))
}

fun Fragment.showToast(string: String){
    this.activity?.runOnUiThread {
        val toast = Toast.makeText(this.activity, string, Toast.LENGTH_SHORT)
        toast.setGravity(Gravity.BOTTOM, 0, 0)
        toast.show()
    }
}

fun Fragment.showToast(@StringRes resId: Int){
    showToast(getString(resId))
}

fun Activity.hideBottomUIMenu() {
    window.hide()
}

inline fun <reified C : Activity> Context.startActivity(options: Bundle? = null, noinline init: Intent.() -> Unit = {}) {
    val intent = newIntent<C>(this).apply(init)
    startActivity(intent, options)
}

inline fun <reified C : Activity> Context.startActivity(vararg params: Pair<String, Any>) {
    val intent = newIntent<C>(this)
    params.forEach {
        when (val value = it.second) {
            is Int -> intent.putExtra(it.first, value)
            is Long -> intent.putExtra(it.first, value)
            is CharSequence -> intent.putExtra(it.first, value)
            is String -> intent.putExtra(it.first, value)
            is Float -> intent.putExtra(it.first, value)
            is Double -> intent.putExtra(it.first, value)
            is Char -> intent.putExtra(it.first, value)
            is Short -> intent.putExtra(it.first, value)
            is Boolean -> intent.putExtra(it.first, value)
            is Serializable -> intent.putExtra(it.first, value)
            is Bundle -> intent.putExtra(it.first, value)
            is Parcelable -> intent.putExtra(it.first, value)
            is Array<*> -> when {
                value.isArrayOf<CharSequence>() -> intent.putExtra(it.first, value)
                value.isArrayOf<String>() -> intent.putExtra(it.first, value)
                value.isArrayOf<Parcelable>() -> intent.putExtra(it.first, value)
            }
            is IntArray -> intent.putExtra(it.first, value)
            is LongArray -> intent.putExtra(it.first, value)
            is FloatArray -> intent.putExtra(it.first, value)
            is DoubleArray -> intent.putExtra(it.first, value)
            is CharArray -> intent.putExtra(it.first, value)
            is ShortArray -> intent.putExtra(it.first, value)
            is BooleanArray -> intent.putExtra(it.first, value)
        }
    }
    startActivity(intent)
}

inline fun <reified C : Activity> Activity.startActivityAndFinish(options: Bundle? = null, noinline init: Intent.() -> Unit = {}) {
    val intent = newIntent<C>(this).apply(init)
    startActivity(intent, options)
    finish()
}

inline fun <reified C : Activity> Activity.startActivityForResult(requestCode: Int = -1, options: Bundle? = null, noinline init: Intent.() -> Unit = {}) {
    val intent = newIntent<C>(this).apply(init)
    startActivityForResult(intent, requestCode, options)
}

inline fun <reified T : Any> newIntent(context: Context): Intent {
    return Intent(context, T::class.java)
}

private fun Window.hide() {
    this.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    this.decorView.setOnSystemUiVisibilityChangeListener {
        val uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                //布局位于状态栏下方
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
                //全屏
                View.SYSTEM_UI_FLAG_FULLSCREEN or
                //隐藏导航栏
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

        this.decorView.systemUiVisibility = if (Build.VERSION.SDK_INT >= 19) {
            uiOptions or 0x00001000
        } else {
            uiOptions or View.SYSTEM_UI_FLAG_LOW_PROFILE
        }
    }
}
fun Any.loge(string: String) {
    val tag = javaClass.name.substring(javaClass.name.lastIndexOf(".") + 1)
    Logger.e(tag, string)
}

fun Any.logd(string: String) {
    val tag = javaClass.name.substring(javaClass.name.lastIndexOf(".") + 1)
    Logger.d(tag, string)
}

fun Activity.setResultOK(intent: Intent? = null) {
    if (intent == null) {
        setResult(Activity.RESULT_OK)
    } else {
        setResult(Activity.RESULT_OK, intent)
    }
}

fun Activity.setResultCanceled() {
    setResult(Activity.RESULT_CANCELED)
}


fun Activity.overridePendingTransitionExt() {
    overridePendingTransition(R.anim.face_zoom_enter, R.anim.face_zoom_exit)
}

fun String.fileOutPutStream(): FileOutputStream {
    return FileOutputStream(this)
}

fun String.fileInputStream(): FileInputStream {
    return FileInputStream(this)
}

fun String.file(): File {
    return File(this)
}

inline fun Context.registerReceiver(crossinline handle: (Intent?) -> Unit, noinline filter: IntentFilter.() -> Unit): BroadcastReceiver {

    val receiver = object : BroadcastReceiver(){
        override fun onReceive(context: Context?, intent: Intent?) {
            handle(intent)
        }
    }
    val f = IntentFilter().apply(filter)
    this.registerReceiver(receiver,f)
    return receiver
}


fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false):View{
    return LayoutInflater.from(context).inflate(layoutRes,this,attachToRoot)
}

fun Context.inflate(@LayoutRes layoutRes: Int, root: ViewGroup? = null):View{
    return LayoutInflater.from(this).inflate(layoutRes,root)
}

/**
 * 获取array.xml中的字符串资源数组string[]
 */
fun Context.getStringArray(resId: Int):Array<String>{
    return this.resources.getStringArray(resId)
}

fun Activity.getHandler(isMainThread: Boolean = true, handleMsg: Handler.(Message) -> Unit): Handler {
    return when(isMainThread){
        true -> {
            object : Handler(Looper.getMainLooper()){
                override fun handleMessage(msg: Message) {
                    handleMsg(this,msg)
                }
            }
        }
        else -> {
            val mHandlerThread = HandlerThread("HandlerThread")
            mHandlerThread.start()
            object : Handler(mHandlerThread.looper){
                override fun handleMessage(msg: Message) {
                    handleMsg(this,msg)
                }
            }
        }
    }
}

fun String.matchArray(array: Array<String>):Boolean{
    array.forEach {
        if (this.contains(it)){
            return true
        }
    }
    return false
}

fun ImageView.loadImage(path: String, @DrawableRes errorRes: Int = R.drawable.ic_launcher, @DrawableRes holderRes: Int = R.drawable.ic_launcher){
    Glide.with(this.context).asDrawable()
            .load(path)
            .thumbnail(0.1f).diskCacheStrategy(DiskCacheStrategy.ALL)
            .skipMemoryCache(false)
            .placeholder(holderRes)
            .error(errorRes)
            .into(this)
}

@UseExperimental(ExperimentalContracts::class)
fun CharSequence?.isNotEmpty2(): Boolean {
    contract {
        returns(true) implies (this@isNotEmpty2 != null)
    }

    return !isNullOrEmpty()
}

@UseExperimental(ExperimentalContracts::class)
fun <T> Collection<T>?.isNotEmpty2(): Boolean {
    contract {
        returns(true) implies (this@isNotEmpty2 != null)
    }

    return !isNullOrEmpty()
}

@UseExperimental(ExperimentalContracts::class)

fun Array<*>?.isNotEmpty2(): Boolean {
    contract {
        returns(true) implies (this@isNotEmpty2 != null)
    }

    return !isNullOrEmpty()
}
